﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Windows.Threading;

namespace senController.classes
{
    class NetworkController
    {
        private Controller _controller;
        private NetworkReader _networkReader;
        private Thread _networkReaderThread;
        private NetworkWriter _networkWriter;
        private Thread _networkWriterThread;
        private TcpListener _tcpListener;
        private NetworkStream _stream;
        private TcpClient _client;
        private bool _switchMode;

        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="portNumber">set portnumber for communication</param>
        /// <param name="ipAdress">set ipadres for communication</param>
        /// <param name="controller">gives the controller to the NetworkController</param>
        public NetworkController(int portNumber, string ipAdress, Controller controller)
        {
            this._switchMode = false;
            this._controller = controller;
            _tcpListener = new TcpListener(IPAddress.Any, portNumber);
            //_tcpListener = new TcpListener(IPAddress.Parse(ipAdress), portNumber);
        }

        /// <summary>
        /// Initialize networkcommunication
        /// </summary>
        /// <returns>success</returns>
        public void InitializeNetwork()
        {
            _client = new TcpClient();
            _tcpListener.Start();
            _controller.Message("Controller Server started");
            new Thread(new ThreadStart(Initialize)).Start();            
        }

        private void Initialize()
        {
            _client = _tcpListener.AcceptTcpClient();
            _controller.Message("Connected to Simulator");
            _controller.btnStartIsEnabled();
            _stream = _client.GetStream();

            _networkReader = new NetworkReader(_stream, this, _switchMode);
            _networkReaderThread = _networkReader.Prepare();
            _networkReaderThread.Start();

            _networkWriter = new NetworkWriter(_stream, this, _switchMode);
            _networkWriterThread = _networkWriter.Prepare();
            _networkWriterThread.Start();

            //disable switch option from now on..
            _controller.btnSwitchDisabled();
        }

        /// <summary>
        /// Set trafficlight to another state
        /// </summary>
        /// <param name="id">trafficlight id</param>
        /// <param name="state">new state</param>
        public void SetTrafficLight(string id, int state)
        {
            commandData command = new commandData();
            command.command = 1;
            command.parameters = id + "," + state;
            //Console.WriteLine(command.parameters);
            try
            {
                _networkWriter.SetCommand(command);
            }
            catch
            {
            }
            
        }

        /// <summary>
        /// Insert new traffic into simulator
        /// </summary>
        /// <param name="type">type traffic</param>
        /// <param name="location">start location</param>
        /// <param name="direction">direction of traffic</param>
        public void SetTraffic(String type, string location, string direction)
        {
            commandData command = new commandData();
            command.command = 0;
            command.parameters = type + "," + location + "," + direction;
            //Console.WriteLine(command.parameters);
            try
            {
                _networkWriter.SetCommand(command);
            }
            catch
            {
            }
        }

        /// <summary>
        /// Get information from network receiver and pass it to controller
        /// </summary>
        /// <param name="information">information string</param>
        public void RetreiveSensorInformation(string information)
        {
            string[] p = information.Split(',');
            _controller.ProcessSensorInformation(p[0], int.Parse(p[1]), p[2]);
        }

        /// <summary>
        /// Procces the incomming commands and decides what to do with it
        /// </summary>
        /// <param name="command">Command code</param>
        /// <param name="parameter">a string</param>
        public void ProccesIncommingCommand(int command, string parameter)
        {
            switch (command)
            {
                //receive sensor value
                case 0:
                    RetreiveSensorInformation(parameter);
                    break;
                default:
                    Console.WriteLine("Invalid command {0} with parameter(s): {1}", command, parameter);
                    break;
            }
        }

        /// <summary>
        /// Switch network mode between readint and readbyte
        /// </summary>
        public void SwitchMode()
        {
            // TRUE:  INT32
            // FALSE: BYTE
            _switchMode = !_switchMode;

            //Notify user
            if (_switchMode)
                _controller.Message("Network transfer type changed to Int32");
            else
                _controller.Message("Network transfer type changed to Byte");
        }
    }
}